package cn.kgc.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.kgc.entity.Menus;
import cn.kgc.entity.Roles;
import cn.kgc.entity.Users;
import cn.kgc.form.RolesAddForm;
import cn.kgc.service.MenusService;
import cn.kgc.service.RolesService;
import cn.kgc.service.UsersService;
import cn.kgc.util.Pager;
import cn.kgc.util.ResultConstant;
import cn.kgc.util.exception.HttpException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wangyue
 * @version 1.0
 */
@RestController
@RequestMapping("/roles")
@Api(tags = "角色管理接口")
@Validated
@Slf4j
@CrossOrigin
@SuppressWarnings("all")
public class RolesController {
    @Resource
    private RolesService rolesService;
    @Resource
    private UsersService usersService;
    @Resource
    private MenusService menusService;

    @GetMapping("/list")
    @ApiOperation(value = "查询所有数据")
    @Cacheable(value = "roles", key = "#root.methodName")
    public List<Roles> selectAll() {
        return rolesService.list();
    }

    @PostMapping("/page")
    @ApiOperation(value = "分页查询数据")
    public Pager<Roles> selectPage(@RequestBody HashMap<String, Object> map) {
        //pageSize  currentPage  roleName
        int pageSize = MapUtil.getInt(map, "pageSize");
        int currentPage = MapUtil.getInt(map, "currentPage");
        String roleName = MapUtil.getStr(map, "roleName");
        //查询条件
        LambdaQueryWrapper<Roles> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(StrUtil.isNotBlank(roleName), Roles::getRoleName, roleName);
        //分页条件
        Page<Roles> page = new Page(currentPage, pageSize);
        return Pager.build(rolesService.page(page, wrapper));
    }

    @GetMapping("/detail/{id}")
    @ApiOperation(value = "查看详细信息")
    @ApiImplicitParam(name = "id", value = "主键", paramType = "path", dataType = "string")
    @Cacheable(value = "roles", key = "#root.methodName+#id")
    public Roles selectOne(@PathVariable Serializable id) {
        return this.rolesService.getById(id);
    }

    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "根据主键删除")
    @ApiImplicitParam(name = "id", value = "主键", paramType = "path", dataType = "string")
    @Caching(
            evict = {
                    @CacheEvict(value = "roles", key = "'selectAll'"),
                    @CacheEvict(value = "roles", key = "'selectOne'+#id"),
                    @CacheEvict(key = "'system:authorities:'+#id")
            }
    )
    public boolean delete(@PathVariable int id) {
        //验证角色id是否被引用
        checkRoleIsUsed(id);
        //删除角色以及角色拥有的菜单
        return rolesService.deleteRolesById(id);
    }

    private void checkRoleIsUsed(int id) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getRoleId, id);
        if (usersService.count(wrapper) > 0) {
            throw new HttpException(ResultConstant.DELETE_ROLE_ERROR1);
        }
    }

    @PostMapping("/save")
    @ApiOperation(value = "新增角色信息")
    @CacheEvict(value = "roles", key = "'selectAll'")
    public boolean save(@RequestBody RolesAddForm form) {
        checkRoleNameIsExist(form.getRoleName());
        Roles roles = new Roles();
        BeanUtil.copyProperties(form, roles);
        return rolesService.save(roles);
    }

    private void checkRoleNameIsExist(String roleName) {
        LambdaQueryWrapper<Roles> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Roles::getRoleName, roleName);
        if (rolesService.count(wrapper) > 0) {
            throw new HttpException(ResultConstant.SAVE_ROLE_NAME_REPEAT_ERROR);
        }
    }

    @GetMapping("/all/menus/{roleId}")
    @ApiOperation(value = "查询所有菜单以及角色拥有的菜单")
    public Map<String, List<Menus>> menus(@PathVariable int roleId) {
        //查询所有的菜单
        List<Menus> list = menusService.list();
        //根据角色id查询角色拥有的菜单
        List<Menus> roleMenus = menusService.findMenusByRoleId(roleId);
        //注意一点:
        // 前端的树形组件中,如果返回了父级菜单,父级菜单下的子菜单都会被选中。
        // 假设父级菜单下有5个子菜单  查询的时候返回的信息中包含了一个父级菜单以及父级菜单下的4个字菜单
        // 前端会将父级菜单下的所有字菜单都选中
        //所以 我们返回角色用户的菜单时 应该将父级菜单给剔除掉
//        HashMap<String, List<Menus>> map = new HashMap<>();
//        map.put("allMenus", list);
//        map.put("roleMenus", roleMenus);
        return Map.of("allMenus", list, "roleMenus", roleMenus);
    }

    @PostMapping("/menus/update")
    @ApiOperation(value = "更新角色拥有的菜单")
    @CacheEvict(key = "'system:authorities:'+#params['roleId']")

    public boolean updateRoleMenus(@RequestBody Map<String, Object> proms) {
        return rolesService.updateRolesMenus(proms);
    }
}
